﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;

namespace SoccerEvaluator.Common
{
	/// <summary>
	/// Contiene funciones recuperar datos de DataTables, DataRows u Objects.
	/// Las funciones aqui contenidas hacen los chequeos pertientes para DBNull o null (nothing en VB.NET)
	/// y en caso de encontrarse estos valores devuelven el valor por defecto del tipo de dato correspondiente.
	/// 
	/// Si es necesario se hace un casting al tipo dato especificado
	/// </summary>
	public class Tools
    {
        #region ToBoolean
        /// <summary>
        /// Devuelve el Booleano en la columna y fila del DataTable especificado.
        /// </summary>
        /// <param name="dt">DataTable que contiene los datos</param>
        /// <param name="row">Numero de la Fila</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Booleano</returns>
        public static bool ToBool(DataTable dt, int row, string columnName)
        {
            if (dt.Rows[row].IsNull(columnName)) return false;
            return Convert.ToBoolean(dt.Rows[row][columnName]);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="columnName"></param>
        /// <returns></returns>
        public static bool ToBool(System.Data.IDataReader dr, string columnName)
        {
            if (dr.IsDBNull(dr.GetOrdinal(columnName))) return false;     

            return dr.GetBoolean(dr.GetOrdinal(columnName));
        }
        /// <summary>
        /// Devuelve el Booleano en la columna del DataRow especificado
        /// </summary>
        /// <param name="dr">DataRow que contiene los datos</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Booleano</returns>
        public static bool ToBool(DataRow dr, string columnName)
        {
            if (dr.IsNull(columnName)) return false;
            return Convert.ToBoolean(dr[columnName]);
        }
        /// <summary>
        /// Devuelve el Booleano contenido en el Object especificado
        /// </summary>
        /// <param name="o">Objecto que contiene el valor</param>
        /// <returns>El Boooleano</returns>
        public static bool ToBool(object o)
        {
            if (o == null || o == DBNull.Value) return false;
            return Convert.ToBoolean(o);
        }
        #endregion

        #region ToInt32
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="columnName"></param>
        /// <returns></returns>
        public static int ToInt(IDataReader dr, string columnName)
        {
            if (dr.IsDBNull(dr.GetOrdinal(columnName)))return 0;            
            
            return dr.GetInt32(dr.GetOrdinal(columnName));
        }
        /// <summary>
        /// Devuelve el Int32 en la columna, fila y DataTable especificado.
        /// </summary>
        /// <param name="dt">DataTable que contiene los datos</param>
        /// <param name="row">Numero de la Fila</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Int32</returns>
        public static int ToInt(DataTable dt, int row, string columnName)
        {
            if (dt.Rows[row].IsNull(columnName)) return 0;
            return Convert.ToInt32(dt.Rows[row][columnName]);
        }
        /// <summary>
        /// Devuelve el Int32 en la columna del DataRow especificado
        /// </summary>
        /// <param name="dr">DataRow que contiene los datos</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Int32</returns>
        public static int ToInt(DataRow dr, string columnName)
        {
            if (dr.IsNull(columnName)) return 0;
            return Convert.ToInt32(dr[columnName]);
        }
        /// <summary>
        /// Devuelve el Int32 contenido en el Object especificado
        /// </summary>
        /// <param name="o">Objecto que contiene el valor</param>
        /// <returns>El Int32</returns>
        public static int ToInt(object o)
        {
            if (o == null || o == DBNull.Value) return 0;
            return Convert.ToInt32(o);
        }
        #endregion

        #region ToByte
        /// <summary>
        /// Devuelve el Byte en la columna, fila y DataTable especificado.
        /// </summary>
        /// <param name="dt">DataTable que contiene los datos</param>
        /// <param name="row">Numero de la Fila</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Byte</returns>
        public static byte ToByte(DataTable dt, int row, string columnName)
        {
            if (dt.Rows[row].IsNull(columnName)) return 0;
            return Convert.ToByte(dt.Rows[row][columnName]);
        }
        /// <summary>
        /// Devuelve el Byte en la columna del DataRow especificado
        /// </summary>
        /// <param name="dr">DataRow que contiene los datos</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Byte</returns>
        public static byte ToByte(DataRow dr, string columnName)
        {
            if (dr.IsNull(columnName)) return 0;
            return Convert.ToByte(dr[columnName]);
        }
        /// <summary>
        /// Devuelve el Byte contenido en el Object especificado
        /// </summary>
        /// <param name="o">Objecto que contiene el valor</param>
        /// <returns>El Byte</returns>
        public static byte ToByte(object o)
        {
            if (o == null || o == DBNull.Value) return 0;
            return Convert.ToByte(o);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="columnName"></param>
        /// <returns></returns>
        public static byte ToByte(IDataReader dr, string columnName)
        {
            if (dr.IsDBNull(dr.GetOrdinal(columnName))) return 0;     

            return dr.GetByte(dr.GetOrdinal(columnName));
        }
        #endregion

        #region ToInt16
        /// <summary>
        /// Devuelve el Int16 en la columna y fila del DataTable especificado.
        /// </summary>
        /// <param name="dt">DataTable que contiene los datos</param>
        /// <param name="row">Numero de la Fila</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Int16</returns>
        public static short ToInt16(DataTable dt, int row, string columnName)
        {
            if (dt.Rows[row].IsNull(columnName)) return 0;
            return Convert.ToInt16(dt.Rows[row][columnName]);
        }
        /// <summary>
        /// Devuelve el Int16 en la columna del DataRow especificado
        /// </summary>
        /// <param name="dr">DataRow que contiene los datos</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Int16</returns>
        public static short ToInt16(DataRow dr, string columnName)
        {
            if (dr.IsNull(columnName)) return 0;
            return Convert.ToInt16(dr[columnName]);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="columnName"></param>
        /// <returns></returns>
        public static short ToInt16(IDataReader dr, string columnName)
        {
            if (dr.IsDBNull(dr.GetOrdinal(columnName))) return 0;     

            return dr.GetInt16(dr.GetOrdinal(columnName));
        }
        /// <summary>
        /// Devuelve el Int16 contenido en el Object especificado
        /// </summary>
        /// <param name="o">Objecto que contiene el valor</param>
        /// <returns>El Int16</returns>
        public static short ToInt16(object o)
        {
            if (o == null || o == DBNull.Value) return 0;
            return Convert.ToInt16(o);
        }
        #endregion

        #region ToInt64
        /// <summary>
        /// Devuelve el Int64 en la columna y fila del DataTable especificado.
        /// </summary>
        /// <param name="dt">DataTable que contiene los datos</param>
        /// <param name="row">Numero de la Fila</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Int64</returns>
        public static long ToInt64(DataTable dt, int row, string columnName)
        {
            if (dt.Rows[row].IsNull(columnName)) return 0;
            return Convert.ToInt64(dt.Rows[row][columnName]);
        }
        /// <summary>
        /// Devuelve el Int64 en la columna del DataRow especificado
        /// </summary>
        /// <param name="dr">DataRow que contiene los datos</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Int64</returns>
        public static long ToInt64(DataRow dr, string columnName)
        {
            if (dr.IsNull(columnName)) return 0;
            return Convert.ToInt64(dr[columnName]);
        }
        /// <summary>
        /// Devuelve el Int64 contenido en el Object especificado
        /// </summary>
        /// <param name="o">Objecto que contiene el valor</param>
        /// <returns>El Int64</returns>
        public static long ToInt64(object o)
        {
            if (o == null || o == DBNull.Value) return 0;
            return Convert.ToInt64(o);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="columnName"></param>
        /// <returns></returns>
        public static long ToInt64(IDataReader dr, string columnName)
        {
            if (dr.IsDBNull(dr.GetOrdinal(columnName))) return 0;     

            return dr.GetInt64(dr.GetOrdinal(columnName));
        }
        #endregion

        #region ToString
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="columnName"></param>
        /// <returns></returns>
        public static string ToString(IDataReader dr, string columnName)
        {
            if (dr.IsDBNull(dr.GetOrdinal(columnName))) return string.Empty;     

            return dr.GetString(dr.GetOrdinal(columnName));
        }
        /// <summary>
        /// Devuelve el string en la columna, fila y DataTable especificado.
        /// </summary>
        /// <param name="dt">DataTable que contiene los datos</param>
        /// <param name="row">Numero de la Fila</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El string</returns>
        public static string ToString(DataTable dt, int row, string columnName)
        {
            if (dt.Rows[row].IsNull(columnName)) return "";
            return Convert.ToString(dt.Rows[row][columnName]);
        }
        /// <summary>
        /// Devuelve el String en la columna del DataRow especificado
        /// </summary>
        /// <param name="dr">DataRow que contiene los datos</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El String</returns>
        public static string ToString(DataRow dr, string columnName)
        {
            if (dr.IsNull(columnName)) return "";
            return Convert.ToString(dr[columnName]);
        }
        /// <summary>
        /// Devuelve el String contenido en el Object especificado
        /// </summary>
        /// <param name="o">Objecto que contiene el valor</param>
        /// <returns>El String</returns>
        public static string ToString(object o)
        {
            if (o == null || o == DBNull.Value) return "";
            return Convert.ToString(o);
        }
        #endregion

        #region ToSingle
        /// <summary>
        /// Devuelve el Single en la columna y fila del DataTable especificado.
        /// </summary>
        /// <param name="dt">DataTable que contiene los datos</param>
        /// <param name="row">Numero de la Fila</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Single</returns>
        public static float ToSingle(DataTable dt, int row, string columnName)
        {
            if (dt.Rows[row].IsNull(columnName)) return 0;
            return Convert.ToSingle(dt.Rows[row][columnName]);
        }
        /// <summary>
        /// Devuelve el Single en la columna del DataRow especificado
        /// </summary>
        /// <param name="dr">DataRow que contiene los datos</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Single</returns>
        public static float ToSingle(DataRow dr, string columnName)
        {
            if (dr.IsNull(columnName)) return 0;
            return Convert.ToSingle(dr[columnName]);
        }
        /// <summary>
        /// Devuelve el Single contenido en el Object especificado
        /// </summary>
        /// <param name="o">Objecto que contiene el valor</param>
        /// <returns>El Single</returns>
        public static float ToSingle(object o)
        {
            if (o == null || o == DBNull.Value) return 0;
            return Convert.ToSingle(o);
        }
        #endregion

        #region ToDouble
        /// <summary>
        /// Devuelve el Double en la columna y fila del DataTable especificado.
        /// </summary>
        /// <param name="dt">DataTable que contiene los datos</param>
        /// <param name="row">Numero de la Fila</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Double</returns>
        public static double ToDouble(DataTable dt, int row, string columnName)
        {
            if (dt.Rows[row].IsNull(columnName)) return 0;
            return Convert.ToDouble(dt.Rows[row][columnName]);
        }
        /// <summary>
        /// Devuelve el Double en la columna del DataRow especificado
        /// </summary>
        /// <param name="dr">DataRow que contiene los datos</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Double</returns>
        public static double ToDouble(DataRow dr, string columnName)
        {
            if (dr.IsNull(columnName)) return 0;
            return Convert.ToDouble(dr[columnName]);
        }
        /// <summary>
        /// Devuelve el Double contenido en el Object especificado
        /// </summary>
        /// <param name="o">Objecto que contiene el valor</param>
        /// <returns>El Double</returns>
        public static double ToDouble(object o)
        {
            if (o == null || o == DBNull.Value) return 0;
            return Convert.ToDouble(o);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="columnName"></param>
        /// <returns></returns>
        public static double ToDouble(IDataReader dr, string columnName)
        {
            if (dr.IsDBNull(dr.GetOrdinal(columnName))) return 0;     

            return dr.GetDouble(dr.GetOrdinal(columnName));
        }
        #endregion

        #region ToDateTime
        /// <summary>
        /// Devuelve el DateTime en la columna, fila y DataTable especificado.
        /// </summary>
        /// <param name="dt">DataTable que contiene los datos</param>
        /// <param name="row">Numero de la Fila</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El DateTime</returns>
        public static DateTime ToDateTime(DataTable dt, int row, string columnName)
        {
            if (dt.Rows[row].IsNull(columnName)) return DateTime.MinValue;
            return Convert.ToDateTime(dt.Rows[row][columnName]);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="columnName"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(IDataReader dr, string columnName)
        {
            if (dr.IsDBNull(dr.GetOrdinal(columnName))) return DateTime.MinValue;     

            return dr.GetDateTime(dr.GetOrdinal(columnName));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="columnName"></param>
        /// <returns></returns>
        public static decimal ToDecimal(System.Data.IDataReader dr, string columnName)
        {
            if (dr.IsDBNull(dr.GetOrdinal(columnName))) return 0;     

            return dr.GetDecimal(dr.GetOrdinal(columnName));
        }
        /// <summary>
        /// Devuelve el DateTime en la columna del DataRow especificado
        /// </summary>
        /// <param name="dr">DataRow que contiene los datos</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El DateTime</returns>
        public static DateTime ToDateTime(DataRow dr, string columnName)
        {
            if (dr.IsNull(columnName)) return DateTime.MinValue;
            return Convert.ToDateTime(dr[columnName]);
        }
        /// <summary>
        /// Devuelve el DateTime contenido en el Object especificado
        /// </summary>
        /// <param name="o">Objecto que contiene el valor</param>
        /// <returns>El DateTime</returns>
        public static DateTime ToDateTime(object o)
        {
            if (o == null || o == DBNull.Value) return DateTime.MinValue;
            return Convert.ToDateTime(o);
        }
        #endregion

        #region ToDecimal

        /// <summary>
        /// Devuelve el Decimal en la columna y fila del DataTable especificado.
        /// </summary>
        /// <param name="dt">DataTable que contiene los datos</param>
        /// <param name="row">Numero de la Fila</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Decimal</returns>
        public static decimal ToDecimal(DataTable dt, int row, string columnName)
        {
            if (dt.Rows[row].IsNull(columnName)) return 0;
            return Convert.ToDecimal(dt.Rows[row][columnName]);
        }
        /// <summary>
        /// Devuelve el Decimal en la columna del DataRow especificado
        /// </summary>
        /// <param name="dr">DataRow que contiene los datos</param>
        /// <param name="columnName">Nombre de la columna</param>
        /// <returns>El Decimal</returns>
        public static decimal ToDecimal(DataRow dr, string columnName)
        {
            if (dr.IsNull(columnName)) return 0;
            return Convert.ToDecimal(dr[columnName]);
        }
        /// <summary>
        /// Devuelve el Decimal contenido en el Object especificado
        /// </summary>
        /// <param name="o">Objecto que contiene el valor</param>
        /// <returns>El Decimal</returns>
        public static decimal ToDecimal(object o)
        {
            if (o == null || o == DBNull.Value) return 0;
            return Convert.ToDecimal(o);
        }
        #endregion
        

		/// <summary>
		/// Devuelve la fila donde el valor especificado es igual al contenido en la columna dada.
		/// </summary>
		/// <param name="dt">DataTable que contiene los datos</param>
		/// <param name="columnName">Nombre de la columna donde se va buscar</param>
		/// <param name="value">Valor que se va a buscar</param>
		/// <returns>El n�mero de la fila, -1 si no se encuentra</returns>
		public static int FindInDataTable(DataTable dt,string columnName,object @value)
		{
			int col=dt.Columns.IndexOf(columnName);
			for(int i=0;i<dt.Rows.Count;i++)
			{
				if(dt.Rows[i][col].Equals(@value))
				{
					return i;
				}
			}
			return -1;
		}
		/// <summary>
		/// Actualiza un DataRow de un DataTable
		/// </summary>
		/// <param name="dt">DataTable</param>
		/// <param name="rowIndex">indice del DataRow a actualizar</param>
		/// <param name="values">Pares de valores de la forma {Nombre de la columna,valor}</param>
		public static void UpdateDataRow(DataTable dt,int rowIndex,params object[] values)
		{
			if(rowIndex>dt.Rows.Count-1) return;
			DataRow dr=dt.Rows[rowIndex];
			for(int i=0;i<values.Length;i+=2)
			{
				if(!dt.Columns.Contains((string)values[i])) continue;
				dr[(string)values[i]]=values[i+1];
			}
		}
		/// <summary>
		/// Agrega los valores especificados a un DataTable
		/// </summary>
		/// <param name="dt">DataTable a ser modificado</param>
		/// <param name="values">secuencia valores, deben estar en el orden correspondiente en el DataTAble</param>
		public static void AddDataRow(DataTable dt,params object[] values)
		{
			dt.Rows.Add(values);
		}
		/// <summary>
		/// Agrega un array de DataRows a un DataTable.  los DataRows deben tener el mismo esquema que el DataTable
		/// </summary>
		/// <param name="dt">DataTable</param>
		/// <param name="dr">Arreglo de DataTable</param>
		public static void AddDataRow(DataTable dt,DataRow[] dr)
		{
			for(int i=0;i<dr.Length;i++)
			{
				dt.ImportRow(dr[i]);
			}
		}
		/// <summary>
		/// Ordena los contenidos de un DataTable de acuerdo con los valores contenidos en la columna especificada
		/// </summary>
		/// <param name="dt">DataTable para ordenar</param>
		/// <param name="NameField">Nombre de la columna por donde se va ordenar</param>
		/// <returns>DataTable con los datos ordenados</returns>
		private static DataTable SortTable(DataTable dt,string NameField)
		{
			DataTable dtSort=dt.Clone();
			DataRow[] dr=dt.Select("",NameField);			
			DataRow[] draux=(DataRow [])dr.Clone();

			for(int i=0;i<draux.Length;i++) dtSort.ImportRow(draux[i]);			
			return dtSort;  
		}
		/// <summary>
		/// Filtra los datos de un DataTable segun el criterio especificado
		/// </summary>
		/// <param name="dt">DataTable para filtrar</param>
		/// <param name="Filter">String conteniendo el filtro</param>
		/// <returns>DataTable con los datos filtrados</returns>
		public static DataTable ApplyFilter(DataTable dt,string Filter)
		{
			DataTable dtResults=dt.Clone();
			DataRow[] dr=dt.Select(Filter);			
			DataRow[] draux=(DataRow [])dr.Clone();
			for(int i=0;i<draux.Length;i++) dtResults.ImportRow(draux[i]);			
			return dtResults; 

		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="dt"></param>
		/// <param name="Filter"></param>
		/// <returns></returns>
		public static DataTable ApplyFilter(DataTable dt,string Filter,string sortExpression)
		{
			DataTable dtResults=dt.Clone();
			DataRow[] dr=dt.Select(Filter,sortExpression);			
			DataRow[] draux=(DataRow [])dr.Clone();
			for(int i=0;i<draux.Length;i++) dtResults.ImportRow(draux[i]);			
			return dtResults; 

		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="dt"></param>
		/// <param name="SortExpression"></param>
		/// <returns></returns>
		public static DataTable SortDataTable(DataTable dt,string SortExpression)
		{
			DataTable dtResults=dt.Clone();
			DataRow[] dr=dt.Select("",SortExpression);			
			DataRow[] draux=(DataRow [])dr.Clone();
			for(int i=0;i<draux.Length;i++) dtResults.ImportRow(draux[i]);			
			return dtResults; 

		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="vector"></param>
		/// <param name="val"></param>
		/// <returns></returns>
		public static int FindInVec(Array vector,object val)
		{
			for(int i=0;i<vector.Length;i++)
			{
				object o=vector.GetValue(i);
				if(o.Equals(val))
				{					
					return i;
				}
			}
			return -1;
		}
		/// <summary>
		/// devuelve un array de objects en un array de strings
		/// </summary>
		/// <param name="vector"></param>		
		/// <returns></returns>
		public static string[] ToStringArray(object[] vector)
		{
			string[] retValue=new string[vector.Length];
			for(int i=0;i<retValue.Length;i++)
			{
				retValue[i]=vector[i].ToString();
				
			}
			return retValue;
		}
		/// <summary>
		/// Convierte un vector de objetos en un cadena de texto
		/// </summary>
		/// <param name="vector"></param>
		/// <param name="separator"></param>
		/// <returns></returns>
		public static string ToStringArray(object[] vector,string separator)
		{
			System.Text.StringBuilder sb=new System.Text.StringBuilder();
			
			for(int i=0;i<vector.Length;i++)
			{
				string text=string.Format("{0}{1}",ToString(vector[i]),separator);
				sb.Append(text);				
			}            

			return sb.ToString();
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="col"></param>
		/// <param name="separator"></param>
		/// <returns></returns>
		public static string ToStringArray(System.Data.DataColumnCollection col,string separator)
		{
			System.Text.StringBuilder sb=new System.Text.StringBuilder();
			
			for(int i=0;i<col.Count;i++)
			{
				string text=string.Format("{0},",ToString(col[i].ColumnName));
				sb.Append(text);				
			}            

			return sb.ToString();
		}
		/// <summary>
		/// Verifica que la excepcion (o excepcion interna) sea una excepcion de SQL debida a un problema de integridad referencial.
		/// </summary>
		/// <param name="e">La Excepcion</param>
		/// <returns>Booleano indicando si es debido a integridad referencial o no.</returns>
		public static bool IsIntegrityException(Exception e)
		{
			SqlException sqlEx;
			sqlEx=e as SqlException;
			if(sqlEx!=null)
			{
				if(sqlEx.Class==16 || sqlEx.Class==14) return true;
			}
			if(e.InnerException!=null) sqlEx=e.InnerException as SqlException;
			if(sqlEx!=null)
			{
				if(sqlEx.Class==16 || sqlEx.Class==14) return true;
			}
			return false;
		}
		/// <summary>
		/// Convierte el contenido de la columna de un DataTable a un string separados por la cadena especificada.
		/// </summary>
		/// <param name="dt">DataTable que contiene los datos.</param>
		/// <param name="columnName">Nombre de la columna que contiene los datos.</param>
		/// <param name="separator">Separador de la lista.</param>
		/// <returns></returns>
		public static string ColumnToString(DataTable dt,string columnName,string separator)
		{
			if(dt.Rows.Count==0) return "";
			int col=dt.Columns.IndexOf(columnName);
			System.Text.StringBuilder sb=new System.Text.StringBuilder(dt.Rows[0][col].ToString());
			for(int i=1;i<dt.Rows.Count;i++)
			{
				sb.Append(separator);
				sb.Append(dt.Rows[i][col]);
			}
			return sb.ToString();
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="dt"></param>
		/// <param name="row"></param>
		/// <param name="columnNames">Nombre de columnas que se desean incluir en el vector</param>
		/// <returns></returns>
		public static string[] RowToString(DataTable dt,int row,params string[] columnNames)
		{
			try
			{			
            
				string[] returnValue=new string[columnNames.Length];

				for(int j=0;j<columnNames.Length;j++)
				{
					returnValue[j]=ToString(dt,row,columnNames[j]);
				}

				return returnValue;
			}
			catch
			{
				return null;
			}
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="dt"></param>
		/// <param name="row"></param>
		/// <param name="columnNames"></param>
		/// <returns></returns>
		public static string[] RowToFormatString(DataTable dt,int row,params string[] columnNames)
		{
			try
			{			
            
				string[] returnValue=new string[columnNames.Length];

				for(int j=0;j<columnNames.Length;j++)
				{
					returnValue[j]=ToFormatString(dt,row,columnNames[j]);
				}

				return returnValue;
			}
			catch
			{
				return null;
			}
		}
		/// <summary>
		/// Convierte un datatable en un array Bi-Dimensional tipo object
		/// Por Henry Rosales P : henryr@softwarelayer.com
		/// 5-4-2004 10:30 ET
		/// </summary>
		/// <param name="dt">DataTable que contiene los datos.</param>	
		/// <returns>Object Array bidimensional con los Datos del Datatable </returns>
		public static object[,] DataTableToArray(DataTable dt)
		{
			
			int rowCnt		= dt.Rows.Count;  
			int colCnt		= dt.Columns.Count; 
					
			object[,] arr	= new object[rowCnt,colCnt];
			
			for(int xIndex=0;xIndex<dt.Rows.Count;xIndex++)
			{				
				for (int yIndex=0; yIndex<dt.Columns.Count; yIndex++)
				{
					object cellData = dt.Rows[xIndex][yIndex];					
					arr[xIndex,yIndex] = cellData; 
				}					
			} 

			return arr;
			

		}
		/// <summary>
		/// Convierte un datatable en un array Bi-Dimensional tipo object
		/// Por Henry Rosales P : henryr@softwarelayer.com
		/// 5-4-2004 10:30 ET
		/// </summary>
		/// <param name="dt">DataTable que contiene los datos.</param>
		/// <param name="columns">Columnas que contienen los datos a ser pasados al array</param>
		/// <returns>Object Array bidimensional con los Datos del Datatable </returns>
		public static object[,] DataTableToArray(DataTable dt,params string[] columns)
		{
			
			int rowCnt		= dt.Rows.Count;  
			int colCnt		= columns.Length; 
					
			object[,] arr	= new object[rowCnt,colCnt];
			
			for(int xIndex=0;xIndex<dt.Rows.Count;xIndex++)
			{				
				for (int yIndex=0; yIndex<columns.Length; yIndex++)
				{
					object cellData = dt.Rows[xIndex][columns[yIndex]];					
					arr[xIndex,yIndex] = cellData; 
				}					
			} 

			return arr;
			

		}
		/// <summary>
		/// Escoje los elementos distintintos en una columna dada de un DataTable
		/// </summary>
		/// <param name="dt">DataTable donde se realizar� la consulta.</param>
		/// <param name="columnName">Nombre de la columna que contiene los datos.</param>
		/// <returns>Arreglo de Objects con los valores distintos</returns>
		public static Array SelectDistinct(DataTable dt,string columnName)
		{
			int col=dt.Columns.IndexOf(columnName);
			object tmp;
			//Array result=new Array();
			System.Collections.ArrayList result=new System.Collections.ArrayList();
			for(int i=0;i<dt.Rows.Count;i++)
			{
				tmp=dt.Rows[i][col];
				if(result.IndexOf(tmp)<0) result.Add(tmp);
			}

			System.Type t;
			if(dt.Rows.Count>0)
			{
				t=dt.Rows[0][col].GetType();
			}
			else
			{
				t=System.Type.GetType("System.String");
			}
			return result.ToArray(t);
		}
		/// <summary>
		/// Retorna el error completo de la exepcion ingresada
		/// </summary>
		/// <param name="ex"></param>
		/// <returns></returns>
		public static string GetAllError(Exception ex)
		{
			//Copia el objeto de exepcion
			Exception t=ex;  
			System.Text.StringBuilder StrResults=new System.Text.StringBuilder();			

			//Recorre hasta que no hayan mas exepciones
			while(t!=null)
			{
				StrResults.Append(t.Message+" ::: ");
				t = t.InnerException;
			}

			StrResults.Append(" StactTrace: "+ex.StackTrace);
			return StrResults.ToString();
		}	
		/// <summary>
		/// Constructor con separador
		/// </summary>
		/// <param name="ex">Exepcion</param>
		/// <param name="Separator">Cadena que separa las exepciones</param>
		/// <returns></returns>
		public static string GetAllError(Exception ex,string Separator)
		{
			//Copia el objeto de exepcion
			Exception t=ex;  
			System.Text.StringBuilder StrResults=new System.Text.StringBuilder();			

			//Recorre hasta que no hayan mas exepciones
			while(t!=null)
			{
				StrResults.Append(t.Message+Separator);
				t = t.InnerException;
			}
			return StrResults.ToString();
		}

		/// <summary>
		/// Convierte un DataTable a un string XML
		/// </summary>
		/// <param name="dt">DataTable con la informaci�n</param>
		/// <param name="dataTableName">Nombre del DataTable</param>
		/// <returns>Cadena XML con la representaci�n del DataTable</returns>
		public static string DataTableToXML(DataTable dt, string dataTableName)
		{
			DataSet dsContents = new DataSet("Contents_"+dataTableName);			
			dt.TableName	   = dataTableName;
			dsContents.Tables.Add(dt);
			return dsContents.GetXml();
		}

		/// <summary>
		/// Convierte un DataTable a un string separado por valores en filas y columnas(ejemplo, ","y ";")
		/// </summary>
		/// <param name="dt">DataTable con la informaci�n</param>
		/// <param name="rowSeparator">Separador de las filas</param>
		/// <param name="columnSeparator">Separador de la columnas</param>
		/// <param name="includeColumnNames">Si incluye o no nombres de las columnas</param>
		/// <returns>Cadena con la representaci�n del DataTable</returns>
		public static string DataTableToString(DataTable dt, string rowSeparator, string columnSeparator, bool includeColumnNames)
		{
			string localData = "";
			if (dt == null || dt.Rows.Count < 1) return localData;
			//Primera fila con nombres de las columnas
			if (includeColumnNames)
			{
				for (int i=0; i<dt.Columns.Count;i++) localData += ToString(dt.Columns[i].ColumnName) + columnSeparator ;
				localData += rowSeparator;
			}
			// A partir de la segunda fila con los datos
			for (int i=0; i<dt.Rows.Count;i++)
			{
				for (int j=0;j<dt.Columns.Count;j++) localData += ToString(dt.Rows[i][j]) + columnSeparator;
				localData.Remove(localData.Length-1,1); 			
				localData += rowSeparator;
			}
			localData.Remove(localData.Length-1,1); 
			return localData;
		}

		/// <summary>
		/// Enumeraci�n para el tipo de ordenamiento de un DataTable
		/// </summary>		
		public enum OrderType
		{
			/// <summary>
			/// Orden Ascendente
			/// </summary>
			ASC=0,
			/// <summary>
			/// Orden Descendente
			/// </summary>
			DESC
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="dt"></param>
		/// <param name="ColumName"></param>
		/// <returns></returns>
		public static decimal DataTableSum(DataTable dt,string ColumName)
		{
			decimal sum=0;
			for(int i=0;i<dt.Rows.Count;i++)
			{
				sum+=ToDecimal(dt,i,ColumName);
			}

			return sum;
		}		
		/// <summary>
		/// Adiciona subtotales a una funcion
		/// </summary>
		/// <param name="dt">DataTable con la fuente de datos</param>
		/// <param name="ColumnIdName">Nombre de la columna que se usa como identificador para el subtotal</param>
		/// <param name="ColumnValue">Nombre de la columna que se quiere totalizar debe ser de tipo numerico</param>
		/// <param name="ColumnCaption"></param>
		public static void AddSubTotal(DataTable dt,string ColumnIdName,string ColumnValue,string ColumnCaption)
		{
			try
			{
				Array values=SelectDistinct(dt,ColumnIdName);

				DataTable dtFilter;

				System.Type t=dt.Rows[0][ColumnIdName].GetType();
			
				string filter="";
				if(t==typeof(string))
				{
					filter="{0}='{1}'";
				}
				else
				{
					filter="{0}={1}";
				}
				double sum=0;
				DataRow dr;
				string captionColumn="";
			
				for(int i=0;i<values.Length;i++)
				{		

					dtFilter=ApplyFilter(dt,string.Format(filter,ColumnIdName,values.GetValue(i)));
					sum=0;

					if(dtFilter.Rows.Count>0)
					{
						DataRow dr1 = dt.NewRow();
						dr1[ColumnCaption]="------------";

						DataRow dr2 = dt.NewRow();
						dr2[ColumnCaption]="============";

						captionColumn="PointExactScores";

						for(int j=0;j<dtFilter.Rows.Count;j++)
						{
							sum+=ToDouble(dtFilter.Rows[j][ColumnValue]);
						}

						dr=dt.NewRow();
					
						dr[ColumnValue]=sum;
						dr[ColumnCaption]=captionColumn;
				
						//Determinar la ultima posicion de elemento
						int pos=FindLastInDataTable(dt,ColumnIdName,values.GetValue(i));					

						if(pos!=-1)
						{
							//Adicionar una fila nueva en el datatable original
							dt.Rows.InsertAt(dr1, pos+1);
							dt.Rows.InsertAt(dr,pos+2);	
							dt.Rows.InsertAt(dr2, pos+3);
						}
					}				
				}
			}
			catch(Exception ex)
			{
				System.Diagnostics.Trace.WriteLine(GetAllError(ex));
			}
		}				
		/// <summary>
		/// Adiciona una fila al final de datatable con los valores de totales especificados
		/// </summary>
		/// <param name="dt">DataTable</param>
		/// <param name="TotalFieldName">Columna para colocar el titulo 'PointExactScores'</param>
		/// <param name="ColumnTotals">Nombre de las columnas que se quieren totalizar</param>
		public static void AddTotal(DataTable dt,string TotalFieldName,Array ColumnTotals)
		{
			double[] totals=new double[ColumnTotals.Length];

			DataRow dr=dt.NewRow();
			
			for(int i=0;i<dt.Rows.Count;i++)
			{	
				for(int j=0;j<ColumnTotals.Length;j++)
				{
					double val=Tools.ToDouble(dt,i,ColumnTotals.GetValue(j).ToString());
					double actualValue=Tools.ToDouble(dr,ColumnTotals.GetValue(j).ToString());
					dr[ColumnTotals.GetValue(j).ToString()]=actualValue+val;					
				}							
			}

			dr[TotalFieldName]="TOTAL";

			//Adiciona la fila de totales al datatable
			dt.Rows.Add(dr);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="dt"></param>
		/// <param name="TotalFieldName"></param>
		/// <param name="columns"></param>
		public static void AddTotal(DataTable dt,string TotalFieldName, params string []columns)
		{
			double[] totals=new double[columns.Length];

			DataRow dr=dt.NewRow();
			
			for(int i=0;i<dt.Rows.Count;i++)
			{	
				for(int j=0;j<columns.Length;j++)
				{
					double val=Tools.ToDouble(dt,i,columns[j]);
					double actualValue=Tools.ToDouble(dr,columns[j]);
					double totalVal=actualValue+val;
					dr[columns[j]]=Convert.ChangeType(totalVal,dt.Columns[columns[j]].DataType);					
				}							
			}

			dr[TotalFieldName]="TOTAL";

			//Adiciona la fila de totales al datatable
			dt.Rows.Add(dr);
		}
		/// <summary>
		/// Adiciona una columna y coloca los totales por filas
		/// </summary>
		/// <param name="dt">Fuente de datos</param>
		/// <param name="columnName">Nombre de la columna donde se calculara el total</param>
		/// <param name="columnStart">Columna de inicio para la sumatoria</param>
		/// <param name="columnEnd">Columna fin para el calculo de la suma</param>
		/// <param name="dType">tipo de Datos de la columna de totales</param>
		/// <returns>Datatable con la modificacion</returns>
		public static DataTable AddRowTotal(DataTable dt,string columnName,int columnStart,int columnEnd,System.Type dType)
		{
			dt.Columns.Add(columnName,dType);

			for(int i=0;i<dt.Rows.Count;i++)
			{
				decimal total=0;
				for(int j=columnStart;j<columnEnd;j++)
				{
					total+=ToDecimal(dt.Rows[i][j]);                    
				}
				dt.Rows[i][columnName]=Convert.ChangeType(total,dType);
			}

			return dt;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="dt"></param>
		/// <param name="columnName"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		public static int FindLastInDataTable(DataTable dt,string columnName,object @value)
		{
			int col=dt.Columns.IndexOf(columnName);
			for(int i=dt.Rows.Count-1;i>=0;i--)
			{
				if(dt.Rows[i][col].Equals(@value))
				{
					return i;
				}
			}
			return -1;
		}
		/// <summary>
		/// Convierte e
		/// </summary>
		/// <param name="text"></param>
		/// <returns></returns>
		public static string TitleCase(string text)
		{
			System.Text.StringBuilder sb=new System.Text.StringBuilder();
			bool capital=true;
			for(int i=0;i<text.Length;i++)
			{
				if(capital)
				{
					sb.Append(char.ToUpper(text[i]));
					capital=false;
				}
				else
				{
					sb.Append(char.ToLower(text[i]));
				}
				if(text[i]==' ') capital=true;
			}
			return sb.ToString();
		}
		/// <summary>
		/// Quita puntos del texto de una C�dula
		/// </summary>
		/// <param name="docNumber">Texto del NIT</param>
		/// <returns>C�dula sin formato</returns>
		public static string RemoveDocNumberFormat(string docNumber)
		{
			return docNumber.Replace(".","");
		}
		/// <summary>
		/// Aplica el formato a una c�dula.
		/// </summary>
		/// <param name="docNumber">C�dula.</param>
		/// <returns>C�dula con el formato.</returns>
		public static string FormatDocNumber(string docNumber)
		{
			string temp=RemoveDocNumberFormat(docNumber);
			if(temp.Length>3)
			{
				int first;
				int groups=Math.DivRem(temp.Length-3,3,out first);
				string result= first==0?"":temp.Substring(0,first)+".";
				for(int i=0;i<groups;i++)
				{
					result+=temp.Substring(first+3*i,3)+".";
				}
				return result+temp.Substring(first+3*groups,3);
			}
			else
			{
				return temp;
			}
		}
		/// <summary>
		/// Registra un evento al evenlog de windows
		/// </summary>
		/// <param name="source"></param>		
		/// <param name="message"></param>
		/// <param name="type"></param>
		public static void WriteWindowsLog(string source,string message,EventLogEntryType type)		
		{
			try
			{	
				EventLog.WriteEntry(source,message,type);		
			}			
			catch(Exception ex)
			{
				System.Diagnostics.Trace.WriteLine(GetAllError(ex));
			}
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="dt"></param>
		/// <param name="columnNames"></param>
		/// <returns></returns>
		public static DataTable GetTotals(DataTable dt,params string[] columnNames)
		{
			DataTable dtResult=dt.Clone();

			DataRow dr=dtResult.NewRow();
			for(int j=0;j<columnNames.Length;j++)
			{
				decimal total=0;
				
				for(int i=0;i<dt.Rows.Count;i++)
				{
					total+=Tools.ToDecimal(dt,i,columnNames[j]);
				}
				dr[columnNames[j]]=total;				
			}

			//Adiciona el total al datatable resultado
			dtResult.Rows.Add(dr);

			return dtResult;
		}
		/// <summary>
		/// Realiza la suma de la columna especificada
		/// </summary>
		/// <param name="dt"></param>
		/// <param name="columnName"></param>		
		/// <returns></returns>
		public static object SumColumn(DataTable dt,string columnName)		
		{
			System.Type type=dt.Columns[columnName].DataType;

			float total=0;
			
			for(int i=0;i<dt.Rows.Count;i++)
			{
				total+=ToSingle(dt,i,columnName);
			}			

			return Convert.ChangeType(total,type);			
		}
		/// <summary>
		/// Ajusta un texto en el numero de caracteres especificado de ancho
		/// </summary>
		/// <param name="text"></param>
		/// <param name="width"></param>
		/// <returns></returns>
		public static string AdjustText(string text,int width)
		{
			if(text.Length>0 && width>0)
			{
				int counter=(int)(text.Length / width);

				if(counter>0)
				{
					int pos=width;			
					for(int i=1;i<=counter;i++)
					{
						//Busca el espacio mas cercano
						int posSpace=text.LastIndexOf(" ",pos);

						//Si no lo encuentra, cortar en pos
						posSpace=posSpace==-1?pos:posSpace;

						//Insertar un salto de seccion
						text=text.Insert(posSpace,"\n");

						//Incrementar el contador de ancho de parrafo
						pos+=width+1;
					}
				}
			}			
			return text;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="o"></param>
		/// <returns></returns>
		public static string ToFormatString(object o)
		{			
			switch(Type.GetTypeCode(o.GetType()))
			{
				case TypeCode.Decimal:					
				case TypeCode.Double:
				case TypeCode.Single:
				case TypeCode.Int32:
					return string.Format("{0,15:N}",o);		
				default:
					return ToString(o);
			}
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="dt"></param>
		/// <param name="row"></param>
		/// <param name="columnName"></param>
		/// <returns></returns>
		public static string ToFormatString(DataTable dt,int row,string columnName)
		{			
			object o=dt.Rows[row][columnName];

			switch(Type.GetTypeCode(o.GetType()))
			{
				case TypeCode.Decimal:					
				case TypeCode.Double:
				case TypeCode.Single:
				case TypeCode.Int32:
					return string.Format("{0,15:N}",o);		
				default:
					return ToString(o);
			}
		}
		/// <summary>
		/// Escribe un datatable a un archivo plano, no se recomienda para datatables grandes
		/// dado que se escribe al archivo registro a registro
		/// </summary>
		/// <param name="dt"></param>
		/// <param name="exportColumnNames"></param>
		/// <param name="pathFile"></param>
		public static void ExportDataTable(DataTable dt,string pathFile,bool exportColumnNames)
		{
			System.IO.StreamWriter sw=null;
			try
			{
				sw=new System.IO.StreamWriter(pathFile,true,System.Text.Encoding.UTF8);
				
				if(exportColumnNames)
				{
					string colNames=ToStringArray(dt.Columns,",");
					sw.WriteLine(colNames.Substring(0,colNames.Length-1));
				}
				
				for(int i=0;i<dt.Rows.Count;i++)
				{
					string registry=ToStringArray(dt.Rows[i].ItemArray,",");

					//Recortar el ultimo caracter de separacion
					registry=registry.Substring(0,registry.Length-1);

					sw.WriteLine(registry);				
				}
			}
			catch(Exception ex)
			{
				throw ex;
			}
			finally
			{
				sw.Close();
			}
		}
		/// <summary>
		/// Exporta un datatable especificando el formato de cada celda
		/// </summary>
		/// <param name="pathFile"></param>
		/// <param name="enc">Tipo de codificacion</param>
		/// <param name="dt">Datatable que se desea exportar</param>
		/// <param name="cellFormat">Vector de formatos uno para cada celda</param>
		public static void ExportDataTable(string pathFile,System.Text.Encoding enc,DataTable dt,params string[] cellFormat)
		{
			System.IO.StreamWriter sw=null;

			#region Verificacion de la cantidad de columnas vs la cantidad de formatos suministrados
			if(cellFormat.Length!=dt.Columns.Count)
			{
				throw new Exception("El numero de columnas debe ser igual al numero de formatos de celda");
			}
			#endregion

			try
			{
				sw=new System.IO.StreamWriter(pathFile,true,enc);			
					
				string registry="";

				for(int i=0;i<dt.Rows.Count;i++)
				{
					registry="";

					for(int j=0;j<dt.Columns.Count;j++)
					{
						registry+=string.Format(cellFormat[j],dt.Rows[i][j]);
					}
                    
					//Escribe el registro
					sw.WriteLine(registry);				
				}
			}
			catch(Exception ex)
			{
				throw ex;
			}
			finally
			{
				sw.Close();
			}
		}
        /// <summary>
        /// Suma las columnas especificadas por filas
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="columnName"></param>
        /// <param name="column"></param>
        /// <param name="type"></param>
        public static void AddColumnSum(DataTable dt, string columnName, string[] column, System.Type type)
        {
            //Adiciona la columna de total
            dt.Columns.Add(columnName, type);

            //Recorre las filas
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                double sum = 0;
                double val = 0;

                for (int j = 0; j < column.Length; j++)
                {
                    try
                    {
                        val = ToDouble(dt.Rows[i][column[j]]);
                    }
                    catch { val = 0; }

                    sum += val;
                }

                dt.Rows[i][columnName] = Convert.ChangeType(sum, type);
            }
        }
        /// <summary>
        /// Adjunta una tabla al final de la otra.  Las tablas deben tener el mismo esquema
        /// </summary>
        /// <param name="dtSource"></param>
        /// <param name="dtAppend"></param>
        public static void AppendTable(DataTable dtSource, DataTable dtAppend)
        {
            for (int i = 0; i < dtAppend.Rows.Count; i++)
            {
                dtSource.Rows.Add(dtAppend.Rows[i].ItemArray);
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public static float ToFloat(IDataReader dr, string columnName)
        {
            if (dr.IsDBNull(dr.GetOrdinal(columnName))) return 0;     

            return dr.GetFloat(dr.GetOrdinal(columnName));
        }


        /// <summary>
        /// 
        /// </summary>        
        /// <param name="item"></param>
        /// <param name="toItem"></param>
        public static void SetProperties(object fromItem,object toItem)
        {
            Type fromType = fromItem.GetType();
            Type toType = toItem.GetType();

            System.Reflection.PropertyInfo[] fromProperties = fromType.GetProperties();

            System.Reflection.PropertyInfo[] toProperties = toType.GetProperties();            

            foreach (System.Reflection.PropertyInfo fromProp in fromProperties)
            {
                try
                {
                    System.Reflection.MethodInfo getMethod = fromProp.GetGetMethod();

                    object val = getMethod.Invoke(fromItem, null);

                    object[] param = new object[] { val };

                    System.Reflection.MethodInfo setMethod = GetSetProperty(fromProp.Name, toProperties).GetSetMethod();

                    setMethod.Invoke(toItem, param);
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Trace.WriteLine(ex.Message);                    
                }
                
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="propertyName"></param>
        /// <param name="toProperties"></param>
        /// <returns></returns>
        private static System.Reflection.PropertyInfo GetSetProperty(string propertyName, System.Reflection.PropertyInfo[] toProperties)
        {
            foreach (System.Reflection.PropertyInfo item in toProperties)
            {
                if (item.Name == propertyName) 
                {
                    return item;
                }
            }

            return null;
        }
    }
}
